package vn.codespot.hms.api;

import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;

import javax.net.ssl.HttpsURLConnection;

import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;

import android.text.TextUtils;

import vn.codespot.hms.model.request.IRequestModel;
import vn.codespot.hms.model.response.IResponseModel;
import vn.codespot.hms.model.response.ResponseModelFactory;
import vn.codespot.hms.utils.HMSUtils;

public class Requester {
    private HttpURLConnection mConn;

    /* Implementation for GET request */
    public IResponseModel doGet(String url, IRequestModel requestModel) throws IOException {
        if (requestModel != null) {
            url = url + HMSUtils.getHttpGetQuery(requestModel.getDataAsMap());
        }
        return doHttpRequest(url, HttpGet.METHOD_NAME, null);
    }

    /* Implementation for POST request */
    public IResponseModel doPost(String url, IRequestModel requestModel) throws IOException {
        return doHttpRequest(url, HttpPost.METHOD_NAME, requestModel);
    }

    public void forceCancelHttpRequest() {
        if (mConn != null) {
            mConn.disconnect();
            mConn = null;
        }
    }

    private IResponseModel doHttpRequest(String url, String methodName, IRequestModel requestModel) throws IOException {
        mConn = null;
        IResponseModel ret = null;
        try {
            mConn = getHttpsUrlConnection(url, methodName);
            sendHttpsRequestData(mConn, requestModel);
            ret = processResponse(mConn);
        } finally {
            if (mConn != null) {
                mConn.disconnect();
                mConn = null;
            }
        }
        return ret;
    }

    private IResponseModel processResponse(HttpURLConnection conn) throws IOException {
        if (conn == null) {
            return null;
        }

        String responseData = getResponseDataAsString(conn.getInputStream());
        return ResponseModelFactory.getIntance().getResponseModel(conn.getURL().getPath(), responseData);
    }

    private String getResponseDataAsString(InputStream inputStream) throws IOException {
        BufferedReader br = null;
        StringBuilder builder = new StringBuilder();
        try {
            br = new BufferedReader(new InputStreamReader(inputStream));
            String input = null;
            while ((input = br.readLine()) != null) {
                builder.append(input);
            }
        } finally {
            if (br != null) {
                br.close();
                br = null;
            }
        }
        return builder.toString();
    }

    private HttpURLConnection getHttpsUrlConnection(String url, String method) throws IOException {
        if (TextUtils.isEmpty(url) && TextUtils.isEmpty(method)) {
            throw new IllegalArgumentException("HTTP URL and method must not be null or empty");
        }

        URL requestUrl = new URL(url);
        URLConnection conn = requestUrl.openConnection();
        HttpURLConnection httpConn;
        if (conn instanceof HttpURLConnection) {
            httpConn = (HttpURLConnection) conn;
        } else {
            httpConn = (HttpsURLConnection) conn;
        }

        httpConn.setRequestMethod(method);
        httpConn.setConnectTimeout(15000);
        return httpConn;
    }

    private void sendHttpsRequestData(HttpURLConnection conn, IRequestModel requestModel) throws IOException {
        if (requestModel == null) {
            return;
        }
        DataOutputStream dos = null;
        try {
            conn.setDoOutput(true);
            conn.setDoInput(true);
            conn.setUseCaches(false);
            // conn.setRequestProperty("Content-Type", "application/json");
            // conn.setRequestProperty("Accept", "application/json");
            conn.connect();
            dos = new DataOutputStream(conn.getOutputStream());
            dos.write(requestModel.convertToJson().getBytes("UTF-8"));
            dos.flush();

            /*arrival_port=HAN&person=1&urgently=1&visa_type=1_month_single&primary_email=minhtrung2606@gmail.com&date_arrival=26-06-2013&coupon_code=&fees=0&secondary_email=&hour=1&purpose=Tourist&date_exit=26-06-2013&note=&applicants[0][passport_exp]=26-06-2013&applicants[0][birthday]=26-06-2013&applicants[0][gender]=male&applicants[0][passport]=123&applicants[0][national]=Afghanistan&applicants[0][name]=nmt*/
        } finally {
            if (dos != null) {
                dos.close();
                dos = null;
            }
        }
    }
}
